/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/commons/json/parser/deserializer/ArrayDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Id: ArrayDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-02 11:09:12 +0800 (Mon, 02 Jul 2012) $
 * $Revision: 1034 $
 */
package com.elancom.framework.commons.json.parser.deserializer;

import java.lang.reflect.Array;
import java.lang.reflect.Type;

import com.elancom.framework.commons.json.JSONArray;
import com.elancom.framework.commons.json.parser.DefaultJSONParser;
import com.elancom.framework.commons.json.parser.JSONLexer;
import com.elancom.framework.commons.json.parser.JSONToken;
import com.elancom.framework.commons.json.util.TypeUtils;

public class ArrayDeserializer implements ObjectDeserializer {

	public final static ArrayDeserializer instance = new ArrayDeserializer();

	@Override
	@SuppressWarnings("unchecked")
	public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
		final JSONLexer lexer = parser.getLexer();
		if (lexer.token() == JSONToken.NULL) {
			lexer.nextToken(JSONToken.COMMA);
			return null;
		}

		if (lexer.token() == JSONToken.LITERAL_STRING) {
			final byte[] bytes = lexer.bytesValue();
			lexer.nextToken(JSONToken.COMMA);
			return (T) bytes;
		}

		final JSONArray array = new JSONArray();
		parser.parseArray(array);

		return toObjectArray(parser, (Class<T>) clazz, array);
	}

	@SuppressWarnings("unchecked")
	private <T> T toObjectArray(DefaultJSONParser parser, Class<T> clazz, JSONArray array) {
		if (array == null) {
			return null;
		}

		final int size = array.size();

		final Class<?> componentType = clazz.getComponentType();
		final Object objArray = Array.newInstance(componentType, size);
		for (int i = 0; i < size; ++i) {
			final Object value = array.get(i);

			if (componentType.isArray()) {
				final Object element = toObjectArray(parser, componentType, (JSONArray) value);
				Array.set(objArray, i, element);
			} else {
				final Object element = TypeUtils.cast(value, componentType, parser.getConfig());
				Array.set(objArray, i, element);
			}
		}

		array.setRelatedArray(objArray);
		array.setComponentType(componentType);
		return (T) objArray; // TODO
	}

	@Override
	public int getFastMatchToken() {
		return JSONToken.LBRACKET;
	}
}
